home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Resource for Source: C/C++
/
Resource for Source - C-C++.iso
/
misc_src
/
knowhow4
/
pcx.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1995-11-01
|
6KB
|
237 lines
#include "pcx.h"
#include "output.h"
void put_pcx_header(FILE* f, pcxheader* p, loc sz, int pal, int planes)
{
if(pal)
get_pcx_header("color.sys", p);
p->bitpx = 1;
p->nplanes = planes;
p->x1 = 0; p->y1 = 0; p->x2 = sz.X - 1; p->y2 = sz.Y - 1;
p->hres = getmaxx() + 1; /* horiz. resolution of display */
p->vres = getmaxy() + 1; /* vert. resolution of display */
p->bplin = (sz.X + 7) >> 3; /* Bytes per line */
p->palinfo = 1; /* Palette info (1=col.,2 = grey) */
if(f != NULL)
fwrite(p, 128, 1, f);
}
/////////////////////////
int get_pcx_header(pcxstream* s, pcxheader* p_h)
{
s->read((uchar*)p_h, sizeof(pcxheader));
return 1;
}
////////////////////////
int get_pcx_header(FILE* file, pcxheader* p_h)
{
return fread(p_h, sizeof(pcxheader), 1, file);
}
////////////////////////
int get_pcx_header(char* fname, pcxheader* p_h)
{
FILE* f;
if((f = fopen(fname, "rb")) == NULL)
return 0;
pcxheader p;
get_pcx_header(f, p_h);
fclose(f);
return 1;
}
///////////////////////////
inline void pcx_put_char(uchar count, uchar ch, FILE* f)
{
if(count > 1 || (0xC0 == (0xC0 & ch)))
fputc(count | 128 | 64, f); // Write counter
fputc(ch, f); // Write pattern
}
//////////////////////////
void pcx_scr_file(rect coord, char* name, int pal)
{
pal = 1;
FILE* f = fopen(name, "wb");
if(coord.corner.X > getmaxx())
coord.corner.X = getmaxx();
pcxheader p;
put_pcx_header(f, &p, loc(coord.width(), coord.height()), pal);
imageP image = (imageP)malloc(imagesize(0, 0, coord.width(), 0));
int x; int y = 0; int count = 1;
int plane;
plane = x = (N_PLANES - 1) * p.bplin; // start of last plane
int shift = 2 * p.bplin;
int height = p.y2 - p.y1 + 1;
getimage(coord.origin.X, coord.origin.Y,
coord.corner.X, coord.origin.Y, image);
unsigned char ch = image->data[x];
while(1)
{
x++;
if(!(x % p.bplin)) // end of scan line or end of plane
{
if(x != p.bplin) // not the end of scan line
x -= shift;
else // end of scan line
{
if(y < height) // not last scan line
{
x = plane;
y++;
getimage(coord.origin.X, coord.origin.Y + y,
coord.corner.X, coord.origin.Y + y, image);
/* The following code, marked !! is absolutely unnecessary and ineffective.
But Painbrush use stop-on-the-scan-line technology. I don't know why.
This code is compatible with Paintbrush.
*/
pcx_put_char(count, ch, f); // !!
count = 0; // !!
ch = image->data[x]; // !!
}
else // last scan line
{
pcx_put_char(count, ch, f);
break;
}
}
}
if(ch == image->data[x])
{
if(count == 63)
{
pcx_put_char(count, ch, f);
count = 1;
}
else
count++;
}
else
{
pcx_put_char(count, ch, f);
count = 1;
ch = image->data[x];
}
}
delete image;
fclose(f);
}
////////////////////////
int pcx_file_scr(char* name, loc pos, int* cells, int mode)
{
if(cells[0] == -1)
return 1;
FILE* f = fopen(name, "rb");
pcxheader p;
if(f == NULL)
{
fclose(f);
return 0;
}
pcxstream pcxF(f);
get_pcx_header(&pcxF, &p);
if(1 != p.bitpx || N_PLANES != p.nplanes) // incompatible modes
return 0;
imageP image = (imageP)malloc(p.bplin * N_PLANES + sizeof(imageType));
image->xmax = (p.x2 - p.x1 + 1 + 7) / 8 * 8 - 1;
image->ymax = 0;
int x; int y = 0; int count;
int plane;
plane = x = (p.nplanes - 1) * p.bplin; // start of last plane
int shift = 2 * p.bplin;
int height = p.y2 - p.y1 + 1;
int height1;
if(cells != NULL)
{
int i = 0;
while(cells[i] != -1)
i++;
height1 = (cells[i - 1] + 80) / 80 * pScreenSet->cell_height
- pos.Y;
height = height > height1 ? height1 : height;
}
int top = cells == NULL ? 0
: cells[0] / 80 * pScreenSet->cell_height - pos.Y;
imageP work = (imageP)malloc(p.bplin * N_PLANES + sizeof(imageP));
work->ymax = 0;
while(y <= height)
{
unsigned char ch = pcxF.get(); // read char
if((ch & 0xC0 )==0xC0) // if two upper bits == 1
{
count = 63 & ch; // use 6 low bits as counter
ch = pcxF.get();
for(int j = 0; j < count; j++)
{
image->data[x] = ch;
x++;
if(x == p.bplin)
{
if(y >= top)
putimage(pos.X, pos.Y + y, image, cells, work,
p.bplin, mode);
x = plane;
y++;
}
else
if(!(x % p.bplin))
x -= shift;
}
}
else
{
(unsigned char)(image->data[x]) = ch;
x++;
if(x == p.bplin)
{
if(y >= top)
putimage(pos.X, pos.Y + y, image, cells, work, p.bplin,
mode);
x = plane;
y++;
}
else
if(!(x % p.bplin))
x -= shift;
}
}
delete image;
delete work;
fclose(f);
return 1;
}
//////////////////////////
/*
void main()
{
if(!init_KNOW_HOW())
return;
// int LIST[] = { 40, 120, 200, 280, 360, 440, 520, -1 };
// pcx_file_scr("about.pcz", loc(0, 0), LIST, COPY_PUT);
pcx_file_scr("g.pcx", loc(0, 0));
pcx_scr_file(rect(64, 40, 191, 300), "work.pcx", 1);
pcx_file_scr("work.pcx", loc(0, 0));
close_KNOW_HOW();
closegraph();
}
*/